const { Document } = require('@langchain/core/documents');
const { RecursiveCharacterTextSplitter } = require('langchain/text_splitter');
const { OllamaEmbeddings } = require('@langchain/ollama');
const { FaissStore } = require('@langchain/community/vectorstores/faiss');
const path = require('path');
const fs = require('fs');

// 初始化 Ollama 嵌入模型
const embeddings = new OllamaEmbeddings({
  baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
  model: process.env.OLLAMA_MAIN_MODEL || "deepseek-r1:8b"
});

// 存储集合映射
const collections = new Map();

class VectorStoreService {
  static textSplitter = new RecursiveCharacterTextSplitter({
    chunkSize: 1000,
    chunkOverlap: 200,
    separators: ["\n\n", "\n", " ", ""],
    keepSeparator: false
  });

  // 判断向量存储集合是否存在
  static vectorStoreCollectionExists(collectionName) {
    const dataDir = path.join(process.cwd(), 'core', 'vectorStore', 'data', 'faiss', collectionName);
    return  fs.existsSync(dataDir);
  }

  // 初始化集合
  static async initCollection(collectionName) {
    try {
      if (!collectionName) {
        throw new Error('集合名称不能为空');
      }

      if (!collections.has(collectionName)) {
        // 确保数据目录存在
        const dataDir = path.join(process.cwd(), 'core', 'vectorStore', 'data', 'faiss');
        if (!fs.existsSync(dataDir)) {
          fs.mkdirSync(dataDir, { recursive: true });
        }

        // 检查是否存在现有的向量存储
        const storePath = path.join(dataDir, collectionName);
        let vectorStore;

        if (fs.existsSync(storePath)) {
          // 加载现有的向量存储
          vectorStore = await FaissStore.load(storePath, embeddings);
        } else {
          // 创建新的向量存储，添加一个默认的空文档以初始化索引
          const defaultDoc = new Document({
            pageContent: "",
            metadata: {
              is_default: true,
              created_at: new Date().toISOString()
            }
          });
          vectorStore = await FaissStore.fromDocuments([defaultDoc], embeddings);
          // 保存向量存储
          await vectorStore.save(storePath);
        }

        collections.set(collectionName, vectorStore);
      }
      return collections.get(collectionName);
    } catch (error) {
      console.error(`初始化集合 ${collectionName} 失败:`, error);
      throw error;
    }
  }

  // 添加文档到向量存储
  static async addDocuments(collectionName, documents) {
    try {
      const vectorStore = await this.initCollection(collectionName);
      
      if (!Array.isArray(documents) || documents.length === 0) {
        throw new Error('documents必须是非空数组');
      }

      // 文档分块处理
      const docs = [];
      for (const doc of documents) {
        let text = '';
        if (typeof doc === 'string') {
          text = doc;
        } else if (doc.text) {
          text = doc.text;
        } else if (doc.pageContent) {
          text = doc.pageContent;
        } else {
          console.warn('跳过无效文档:', doc);
          continue;
        }

        const splits = await this.textSplitter.splitText(text);
        const metadata = doc.metadata || {};
        
        docs.push(...splits.map(content => new Document({
          pageContent: content,
          metadata: {
            ...metadata,
            chunk_size: content.length,
            created_at: new Date().toISOString()
          }
        })));
      }
      
      if (docs.length === 0) {
        throw new Error('没有有效的文档内容可以添加');
      }

      // 添加到向量存储
      await vectorStore.addDocuments(docs);
      
      // 保存更新后的向量存储
      const storePath = path.join(process.cwd(), 'core', 'vectorStore', 'data', 'faiss', collectionName);
      await vectorStore.save(storePath);

      return {
        success: true,
        count: docs.length
      };
    } catch (error) {
      console.error(`添加文档到集合 ${collectionName} 失败:`, error);
      throw error;
    }
  }

  // 相似度搜索
  static async similaritySearch(collectionName, query, k = 3) {
    try {
      if (!query) {
        throw new Error('搜索查询不能为空');
      }

      const vectorStore = await this.initCollection(collectionName);
      
      // 执行相似度搜索
      const results = await vectorStore.similaritySearchWithScore(query, k);
      
      // 格式化结果
      return results.map(([doc, score]) => ({
        content: doc.pageContent,
        metadata: {
          ...doc.metadata,
          similarity_score: score,
          matched_at: new Date().toISOString()
        }
      }));
    } catch (error) {
      console.error(`在集合 ${collectionName} 中搜索失败:`, error);
      throw error;
    }
  }

  // 删除文档
  static async deleteDocuments(collectionName, filter) {
    try {
      const vectorStore = await this.initCollection(collectionName);
      // FAISS不支持按元数据过滤删除，这里我们重新创建一个空的向量存储
      const storePath = path.join(process.cwd(), 'core', 'vectorStore', 'data', 'faiss', collectionName);
      const newVectorStore = await FaissStore.fromDocuments([], embeddings);
      await newVectorStore.save(storePath);
      collections.set(collectionName, newVectorStore);
      return true;
    } catch (error) {
      console.error(`从集合 ${collectionName} 删除文档失败:`, error);
      throw error;
    }
  }
}

module.exports = VectorStoreService;